home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 651-660 / 658 / view / dcback / dcback.c next >
C/C++ Source or Header  |  1995-03-15  |  14KB  |  428 lines

  1. /*-- AutoRev header do NOT edit!
  2. *
  3. *   Program         :   dcback.c
  4. *   Copyright       :   © 1991 Jaba Development
  5. *   Author          :   Jan van den Baard
  6. *   Creation Date   :   16-Nov-91
  7. *   Current version :   1.2
  8. *   Translator      :   DICE v2.6.
  9. *
  10. *   REVISION HISTORY
  11. *
  12. *   Date          Version         Comment
  13. *   ---------     -------         ------------------------------------------
  14. *   29-Feb-92     1.2             Now uses "SetArgStr()".
  15. *   23-Nov-91     1.1             Command line promting now allowed.
  16. *   16-Nov-91     1.0             Auto detach 2.0 argument parsing startup.
  17. *
  18. *-- REV_END --*/
  19.  
  20. #include <exec/types.h>
  21. #include <exec/memory.h>
  22. #include <exec/execbase.h>
  23. #include <exec/libraries.h>
  24. #include <exec/alerts.h>
  25. #include <dos/dos.h>
  26. #include <dos/dosextens.h>
  27. #include <dos/rdargs.h>
  28. #include <workbench/startup.h>
  29.  
  30. #include <clib/exec_protos.h>
  31. #include <clib/dos_protos.h>
  32.  
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <fcntl.h>
  36. #include <lib/misc.h>
  37.  
  38. /*
  39.  * --- These globals MUST be defined somewhere in your source!
  40.  */
  41. extern  UBYTE   *_procname;         /* process name */
  42. extern  UBYTE   *_template;         /* commandline template */
  43. extern  UBYTE   *_exthelp;          /* extended command line help */
  44. extern  LONG     _stack;            /* process stack */
  45. extern  LONG     _priority;         /* process priority */
  46. extern  LONG     _BackGroundIO;     /* open background io channel */
  47.  
  48. /*
  49.  * --- externally referenced structures.
  50.  */
  51. extern struct ExecBase  *SysBase;   /* to check for V36 minimum */
  52. extern struct WBStartup *_WBMsg;    /* guess what.... */
  53.  
  54. /*
  55.  * --- This is how both main() and wbmain() are called.
  56.  */
  57. extern long main( long, long * );
  58. extern long wbmain( struct WBStartup * );
  59.  
  60. /*
  61.  * --- Proto for the exit routine
  62.  */
  63. long exit( long );
  64.  
  65. /*
  66.  * --- Data that isn't chucked in the BSS section.
  67.  */
  68. BPTR             _DetachDir      =       0l;    /* process current dir */
  69. BPTR             _Backstdout     =       0l;    /* io channel */
  70. UBYTE            _IsDetached     =       FALSE; /* detached flag */
  71. ULONG           *_DosArray       =       0l;    /* commandline array */
  72. UWORD            _NumArgs        =       0l;    /* max # of args */
  73. UBYTE           *_Arguments      =       0l;    /* argument line */
  74. struct RDArgs   *_DosSource      =       0l;    /* for the arguments */
  75.  
  76. /*
  77.  * --- New _main() which checks if it is run from the shell or
  78.  * --- the workbench.
  79.  */
  80. __stkargs long _main( long len, char *lin )
  81. {
  82.     struct Process              *ThisTask;
  83.     struct CommandLineInterface *cli;
  84.     struct MemList              *mlist;
  85.     BPTR                        *SegList, *TmpSeg, StdOut;
  86.     ULONG                        SegCount = 0l, ArgCount = 0l;
  87.     BYTE                         DetachRun = FALSE;
  88.     UBYTE                       *Tmp;
  89.     ULONG                        alert;
  90.  
  91.    /*
  92.     * --- First we must see wether we are running
  93.     * --- under 2.0 or not. We need 2.0 for the
  94.     * --- commandline parsing!
  95.     */
  96.     if ((( struct Library *)SysBase)->lib_Version < 36 )
  97.         return( RETURN_FAIL );
  98.  
  99.    /*
  100.     * --- Get a pointer to our Task (Process)
  101.     */
  102.     ThisTask = ( struct Process * )SysBase->ThisTask;
  103.  
  104.    /*
  105.     * --- When run from the shell the process has
  106.     * --- a CLI structure. If this is the case
  107.     * --- the 'DetachRun' flag is set to TRUE so we
  108.     * --- we know that the program still has to be
  109.     * --- detached.
  110.     */
  111.     if ( ThisTask->pr_CLI )
  112.         DetachRun = TRUE;
  113.  
  114.    /*
  115.     * --- When either the 'DetachRun' or '_IsDetached' flag
  116.     * --- is TRUE it means that we are run from the shell.
  117.     */
  118.     if ( DetachRun || _IsDetached ) {
  119.        /*
  120.         * --- Check if we are detached yet...
  121.         */
  122.         if ( ! _IsDetached ) {
  123.            /*
  124.             * --- We arn't detached yet so we must parse
  125.             * --- the arguments given to us by the shell.
  126.             */
  127.             if ( Tmp = _template ) {
  128.                /*
  129.                 * --- There is a template string supplied
  130.                 */
  131.                 if ( *Tmp ) {
  132.                    /*
  133.                     * --- The template string even got characters in it!
  134.                     * --- Now we must count the maximum number of arguments
  135.                     * --- we can expect. This is done by counting the
  136.                     * --- commas in the template string and then adding
  137.                     * --- one to the result
  138.                     */
  139.                     while ( *Tmp ) {
  140.                         if ( *Tmp == ',' ) ArgCount++;
  141.                         Tmp++;
  142.                     }
  143.                     ArgCount++;
  144.                 }
  145.             }
  146.  
  147.            /*
  148.             * --- Allocate and parse the arguments.
  149.             */
  150.             if ( ArgCount ) {
  151.                /*
  152.                 * --- There are arguments to be expected.
  153.                 */
  154.                 _NumArgs   = ArgCount; /* save argument count */
  155.                 _Arguments = lin;      /* save the argument line pointer */
  156.  
  157.                /*
  158.                 * --- Allocate our RDArgs structure.
  159.                 */
  160.                 if ( ! ( _DosSource = ( struct RDArgs * )AllocVec((long)sizeof( struct RDArgs ), MEMF_PUBLIC | MEMF_CLEAR ))) {
  161.                     alert = AT_Recovery | AG_NoMemory | AO_Unknown;
  162.                     goto suError;
  163.                 }
  164.  
  165.                /*
  166.                 * --- Setup the RDArgs structure for extended help.
  167.                 */
  168.                 _DosSource->RDA_ExtHelp          = _exthelp;
  169.  
  170.                /*
  171.                 * --- Try to allocate the array that will hold
  172.                 * --- the result of the parse.
  173.                 */
  174.                 if ( ! (_DosArray = (ULONG *)AllocVec( ArgCount * sizeof( LONG ), MEMF_PUBLIC | MEMF_CLEAR ))) {
  175.                     alert = AT_Recovery | AG_NoMemory | AO_Unknown;
  176.                     goto suError;
  177.                 }
  178.  
  179.                /*
  180.                 * --- Try to parse the arguments from STDIN.
  181.                 */
  182.                 if ( ! ReadArgs( _template, _DosArray, _DosSource )) {
  183.                     if ( StdOut = Output())
  184.                         Write( StdOut, "Bad Args\n", 9l );
  185.                     alert = 0l;
  186.                     goto suError;
  187.                 }
  188.             }
  189.         }
  190.  
  191.        /*
  192.         * --- This code only get's executed when the program
  193.         * --- was started from the shell and isn't detached yet.
  194.         */
  195.         if ( cli = ( struct CommandLineInterface * )BADDR( ThisTask->pr_CLI )) {
  196.            /*
  197.             * --- Get a copy of the lock to the current directory
  198.             */
  199.             CurrentDir( _DetachDir = CurrentDir( 0l ));
  200.             _DetachDir  = DupLock( _DetachDir );
  201.  
  202.            /*
  203.             * --- Mark us as detached ( a little premature but so what.. )
  204.             */
  205.             _IsDetached = TRUE;
  206.  
  207.            /*
  208.             * --- Open a io channel if requested
  209.             */
  210.             if ( _BackGroundIO )
  211.                 _Backstdout = Open( "*", MODE_OLDFILE );
  212.  
  213.            /*
  214.             * --- Sanity check. If the stack is 0 then make the stack 4096
  215.             */
  216.             if ( ! _stack )
  217.                 _stack = 4096l;
  218.  
  219.            /*
  220.             * --- Try to launch us as a non-cli process
  221.             */
  222.             if ( CreateProc(  _procname, _priority, cli->cli_Module, _stack )) {
  223.                /*
  224.                 * --- Don't rip the code out from under us
  225.                 */
  226.                 cli->cli_Module = 0l;
  227.  
  228.                /*
  229.                 * --- We must make sure that dos doesn't deallocate
  230.                 * --- our arguments before we get a chance to use
  231.                 * --- them.
  232.                 */
  233.                 SetArgStr( 0l );
  234.  
  235.                 return ( RETURN_OK );
  236.             } else {
  237.                 alert = AT_Recovery | AG_ProcCreate | AO_Unknown;
  238.                 goto suError;
  239.             }
  240.         } else {
  241.            /*
  242.             * --- Getting here means that we now run as a non-cli
  243.             * --- process initially started from a shell.
  244.             */
  245.             if ( ! strcmp( ThisTask->pr_Task.tc_Node.ln_Name, _procname )) {
  246.  
  247.                /*
  248.                 * --- Now we are running detached we must make sure that
  249.                 * --- dos deallocates the commandline (if there) when
  250.                 * --- we exit.
  251.                 */
  252.                 SetArgStr( _Arguments );
  253.  
  254.                /*
  255.                 * --- Now we must make sure that we get deallocated
  256.                 * --- when the program exits. This is done by creating
  257.                 * --- a MemList with pointers to all our segments in
  258.                 * --- it and then AddTail'ing this to the Task it's
  259.                 * --- MemList which automatically get's deallocated
  260.                 * --- by the system.
  261.                 */
  262.                 SegList = ( BPTR * )BADDR( ThisTask->pr_SegList );
  263.                 SegList = ( BPTR * )BADDR( SegList[3] );
  264.                 TmpSeg  = SegList;
  265.  
  266.                /*
  267.                 * --- Count the number of segments we have.
  268.                 */
  269.                 while ( SegList ) {
  270.                     SegList = ( BPTR * )BADDR( *SegList );
  271.                     SegCount++;
  272.                 }
  273.  
  274.                /*
  275.                 * --- Try to allocate a MemList with enough MemEntry's
  276.                 * --- I didn't use AllocVec because the system deallocates
  277.                 * --- this structure itself with FreeMem() and not FreeVec()
  278.                 * --- (I think........)
  279.                 */
  280.                 if ( mlist = ( struct MemList * )AllocMem( sizeof( struct MemList ) + sizeof( struct MemEntry ) * ( SegCount - 1 ), MEMF_PUBLIC | MEMF_CLEAR )) {
  281.  
  282.                     SegList  = TmpSeg;
  283.                     mlist->ml_NumEntries = SegCount;
  284.                     SegCount = 0l;
  285.  
  286.                    /*
  287.                     * --- Initialize all MemEntries
  288.                     */
  289.                     while ( SegList ) {
  290.                         mlist->ml_me[ SegCount ].me_Addr   = (APTR)&SegList[ -1 ];
  291.                         mlist->ml_me[ SegCount ].me_Length = SegList[ -1 ];
  292.                         SegList = ( BPTR * )BADDR( *SegList );
  293.                         SegCount++;
  294.                     }
  295.  
  296.                    /*
  297.                     * --- Add our MemList to the Task it's MemList.
  298.                     */
  299.                     AddTail( &ThisTask->pr_Task.tc_MemEntry, &mlist->ml_Node );
  300.  
  301.                    /*
  302.                     * --- Set our current dir
  303.                     */
  304.                     CurrentDir( _DetachDir );
  305.  
  306.                    /*
  307.                     * --- If an io channel was requested we must
  308.                     * --- initialize the proper stdio structures
  309.                     */
  310.                     if ( _BackGroundIO ) {
  311.                         ThisTask->pr_COS = _Backstdout;
  312.  
  313.                         _IoStaticFD[1].fd_Fh    =   _Backstdout;
  314.                         _IoStaticFD[1].fd_Flags =   O_RDWR | O_NOCLOSE | O_ISOPEN;
  315.                         _IoStaticFD[2].fd_Fh    =   _Backstdout;
  316.                         _IoStaticFD[2].fd_Flags =   O_RDWR | O_NOCLOSE | O_ISOPEN;
  317.  
  318.                         _finitdesc( stdout,  1, __SIF_WRITE | __SIF_NOFREE );
  319.                         _finitdesc( stderr,  2, __SIF_WRITE | __SIF_NOFREE );
  320.                     }
  321.  
  322.                    /*
  323.                     * --- Now we just exit with whatever main()
  324.                     * --- returns to us.
  325.                     */
  326.                     exit( main( (long)_NumArgs, _DosArray ));
  327.  
  328.                 } else {
  329.                     alert = AT_Recovery | AG_NoMemory | AO_Unknown;
  330.                     goto suError;
  331.                 }
  332.             }
  333.         }
  334.     } else {
  335.        /*
  336.         * --- Getting here means we have been started from the workbench.
  337.         */
  338.         if ( _WBMsg->sm_ArgList )
  339.            /*
  340.             * --- CurrentDir to the directory we are started from
  341.             */
  342.             CurrentDir( _WBMsg->sm_ArgList->wa_Lock );
  343.  
  344.        /*
  345.         * --- Now we just exit with whatever wbmain()
  346.         * --- returns to us.
  347.         */
  348.         exit( wbmain( _WBMsg ));
  349.     }
  350.  
  351.    /*
  352.     * --- This is never called! It just brings in the code that
  353.     * --- waits for the Workbench message for when we are started
  354.     * --- from the workbench! See wbmain.a!
  355.     */
  356.     _waitwbmsg();
  357.  
  358.    /*
  359.     * --- Here's where we land when something failed.
  360.     * --- This cleans up the mess we made except when we
  361.     * --- got here because the MemList could not be
  362.     * --- allocated! If that's the case the segments wont
  363.     * --- be deallocated. This shouldn't be a problem
  364.     * --- because when the MemList cannot be allocated anymore
  365.     * --- your system is really fuc#@$$##@ up!
  366.     */
  367. suError:
  368.     if ( _DosSource ) {
  369.         FreeArgs( _DosSource );
  370.         FreeVec( _DosSource );
  371.     }
  372.     if ( _DosArray )    FreeVec( _DosArray );
  373.     if ( _DetachDir )   UnLock( _DetachDir );
  374.     if ( alert )        Alert( alert );
  375.     return( RETURN_FAIL );
  376. }
  377.  
  378. #include <lib/atexit.h>
  379.  
  380. typedef struct Process Process;
  381.  
  382. AtExit *_ExitBase;
  383.  
  384. /*
  385.  * --- A New exit which cleans up the mess we made.
  386.  */
  387. long exit( long code )
  388. {
  389.     AtExit *eb;
  390.  
  391.    /*
  392.     * --- If opened, close the io channel
  393.     */
  394.     if ( _Backstdout )
  395.         Close( _Backstdout );
  396.  
  397.    /*
  398.     * --- UnLock our current dir
  399.     */
  400.     if ( _DetachDir )
  401.         UnLock( _DetachDir );
  402.  
  403.    /*
  404.     * --- Deallocate our argument array
  405.     */
  406.     if ( _DosArray )
  407.         FreeVec( _DosArray );
  408.  
  409.    /*
  410.     * --- Cleanup our RDArgs structure
  411.     */
  412.     if ( _DosSource ) {
  413.         FreeArgs( _DosSource );
  414.         FreeVec( _DosSource );
  415.     }
  416.  
  417.    /*
  418.     * --- Ask Matthew...... I don't know!
  419.     */
  420.     for (eb = _ExitBase; eb; eb = eb->Next)
  421.         (*eb->Func)();
  422.  
  423.    /*
  424.     * --- Low level exit
  425.     */
  426.     _exit(code);
  427. }
  428.